package com.qf.web.service.impl;
import com.qf.common.base.exception.ServiceException;
import com.qf.common.base.result.ResultCode;
import com.qf.web.common.qo.ShopkeeperQo;
import com.qf.web.common.vo.ShopkeeperVo;
import com.qf.web.common.qo.ShopkeeperRequestParams;
import com.qf.web.common.utils.ConstantUtils;
import com.qf.web.common.utils.ShiroUtils;
import com.qf.web.dao.BaseRedisDao;
import com.qf.web.entity.Shop;
import com.qf.web.entity.Shopkeeper;
import com.qf.web.mapper.ShopkeeperMapper;
import com.qf.web.service.FlowingWaterService;
import com.qf.web.service.MsgService;
import com.qf.web.service.ShopkeeperService;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.Date;

/**
 * @author 51993
 */
@Service
public class ShopkeeperServiceImpl implements ShopkeeperService {

    @Autowired
    ShopkeeperMapper shopkeeperMapper;

    @Autowired
    HashedCredentialsMatcher hashedCredentialsMatcher;

    @Autowired
    MsgService msgService;

    @Autowired
    BaseRedisDao baseRedisDao;

    @Resource
    FlowingWaterService flowingWaterService;

    @Override
    public Integer updateShopkeeper(ShopkeeperRequestParams requestParams) {
        Shopkeeper shopkeeper = new Shopkeeper();
        //QO 转 PO
        BeanUtils.copyProperties(requestParams,shopkeeper);
        Integer res = shopkeeperMapper.updateShokeeper(shopkeeper);
        if (res < 0){
            //更新失败，抛出异常
            throw new ServiceException(ResultCode.BUSINESS_UNKNOW_ERROR);
        }
        //更新成功
        return res;
    }

    @Override
    public void checkPayPwd(ShopkeeperRequestParams requestParams) {
        //查询用户支付密码
        Shopkeeper shopkeeper = shopkeeperMapper.selectById(requestParams.getShopkeeperId());
        UsernamePasswordToken token = new UsernamePasswordToken(shopkeeper.getShopkeeperPhone(), requestParams.getShopkeeperPayPassword());
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(shopkeeper,shopkeeper.getShopkeeperPayPassword(),null,shopkeeper.getShopkeeperPhone());
        //支付密码匹对
        if (!hashedCredentialsMatcher.doCredentialsMatch(token, info)){
            //密码不匹配，抛出异常
            throw new ServiceException(ResultCode.PASSWORD_MATCH_ERROR);
        }
    }

    @Override
    public ShopkeeperVo selectShopkeeperById(Integer id) {
        Shopkeeper shopkeeper = shopkeeperMapper.selectById(id);
        if (ObjectUtils.isEmpty(shopkeeper)){
            //如果找不到对象，抛出异常
            throw new ServiceException(ResultCode.ACCOUNT_NOT_EXIST);
        }
        //PO 转 VO
        ShopkeeperVo shopkeeperVo = new ShopkeeperVo();
        BeanUtils.copyProperties(shopkeeper,shopkeeperVo);
        return shopkeeperVo;
    }

    @Override
    public void checkAccountPwd(ShopkeeperRequestParams requestParams) {
        Shopkeeper shopkeeper = shopkeeperMapper.selectById(requestParams.getShopkeeperId());
        UsernamePasswordToken token = new UsernamePasswordToken(requestParams.getShopkeeperPhone(), requestParams.getShopkeeperPassword());
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(shopkeeper, shopkeeper.getShopkeeperPassword(), null, shopkeeper.getShopkeeperPhone());
        //密码匹对
        if (!hashedCredentialsMatcher.doCredentialsMatch(token, info)){
            //密码不匹配，抛出异常
            throw new ServiceException(ResultCode.PASSWORD_MATCH_ERROR);
        }
    }

    @Override
    public Integer updateAccountPwd(ShopkeeperRequestParams requestParams) {
        //先对新密码进行加密
        String newPwd = ShiroUtils.encryption(requestParams.getShopkeeperPassword(),null);
        requestParams.setShopkeeperPassword(newPwd);
        //QO 转 PO
        Shopkeeper shopkeeper = new Shopkeeper();
        BeanUtils.copyProperties(requestParams,shopkeeper);
        Integer res = shopkeeperMapper.updateShokeeper(shopkeeper);
        if (res < 0){
            //更新失败，抛出异常
            throw new ServiceException(ResultCode.BUSINESS_UNKNOW_ERROR);
        }
        return res;
    }

    @Override
    public Integer updateAccountPayPwd(ShopkeeperRequestParams requestParams) {
        //先对支付密码进行加密
        String newPayPwd = ShiroUtils.encryption(requestParams.getShopkeeperPayPassword(), null);
        requestParams.setShopkeeperPayPassword(newPayPwd);
        //QO 转 PO
        Shopkeeper shopkeeper = new Shopkeeper();
        BeanUtils.copyProperties(requestParams,shopkeeper);
        Integer res = shopkeeperMapper.updateShokeeper(shopkeeper);
        if (res < 0){
            throw new ServiceException(ResultCode.BUSINESS_UNKNOW_ERROR);
        }
        return res;
    }

    @Override
    public Integer updatePhone(ShopkeeperRequestParams requestParams) {
        //QO 转 PO
        Shopkeeper shopkeeper = new Shopkeeper();
        BeanUtils.copyProperties(requestParams,shopkeeper);
        Integer res = shopkeeperMapper.updateShokeeper(shopkeeper);
        if (res <0 ){
            //更新失败，抛出异常
            throw new ServiceException(ResultCode.BUSINESS_UNKNOW_ERROR);
        }
        return res;
    }

    @Override
    public void sendForgetMsg(String phone, String key) {
        //发送短信
        msgService.sendMsg(phone,key);
    }

    @Override
    public void verifyMsg(ShopkeeperRequestParams requestParams, String key) {
        //根据前缀+手机号去redis中取验证码
        String msgCode = (String) baseRedisDao.getForValue(key + requestParams.getShopkeeperPhone());
        if (msgCode == null){
            //验证码已过期
            throw new ServiceException(ResultCode.MSG_CODE_TIMEOUT);
        }
        //验证码进行判断
        if (!msgCode.equals(requestParams.getPayCode())){
            //验证码不匹配
            throw new ServiceException(ResultCode.CODE_NOT_MATCH);
        }
        //校验通过后把验证码从redis中移除
        baseRedisDao.delete(key+requestParams.getShopkeeperPhone());
    }

    @Override
    public Integer register(ShopkeeperRequestParams requestParams) {
        //设置注册时间
        requestParams.setRegisterTime(new Date());
        //QO 转 PO
        Shopkeeper shopkeeper = new Shopkeeper();
        BeanUtils.copyProperties(requestParams,shopkeeper);
        Integer res = shopkeeperMapper.insertShopkeeper(shopkeeper);
        if(res < 0){
            throw new ServiceException(ResultCode.ACCOUNT_LOGIN_ERROR);
        }
        return res;
    }

    @Override
    public Shopkeeper selectShopkeeperByPhone(String tel) {
        Shopkeeper shopkeeper = shopkeeperMapper.selectShokeeperByTel(tel);
        if (ObjectUtils.isEmpty(shopkeeper)){
            throw new ServiceException(ResultCode.ACCOUNT_NOT_EXIST);
        }
        return shopkeeper;
    }

    @Override
    public void sendMsg(String phone, String accountForgetKeyPrefix) {
        msgService.sendMsg(phone,accountForgetKeyPrefix);
    }

    @Override
    public void verifyAccountMsg(String phone, String code) {
        //先判断验证码是否正确
        String redisCode = (String) baseRedisDao.getForValue(ConstantUtils.ACCOUNT_FORGET_KEY_PREFIX + phone);
        if (ObjectUtils.isEmpty(redisCode)){
            //验证码超时
            throw new ServiceException(ResultCode.MSG_CODE_TIMEOUT);
        }
        if (!redisCode.equals(code)){
            //验证码输入不正确
            throw new ServiceException(ResultCode.CODE_NOT_MATCH);
        }
        //验证码正确，不管后面手机号是否与商户绑定都将验证码从redis中移除
        baseRedisDao.delete(ConstantUtils.ACCOUNT_FORGET_KEY_PREFIX+phone);
        //判断手机号是否与已经注册商户绑定
        Shopkeeper shopkeeper = shopkeeperMapper.selectShokeeperByTel(phone);
        if (ObjectUtils.isEmpty(shopkeeper)){
            //手机号未与已经注册的商户绑定
            throw new ServiceException(ResultCode.ACCOUNT_NOT_EXIST);
        }
        //其余情况均可以让商户重新设置密码
    }

    @Override
    public Integer updateShopkeeperWallet(ShopkeeperQo shopkeeperQo) {
        //充值金额
        Integer rSet = shopkeeperMapper.updateShopkeeperWallet(shopkeeperQo.getMoney(), shopkeeperQo.getShopkeeperId());
        if (rSet == 0){
            throw new ServiceException(ResultCode.ERROR);
        }
        //生成流水
        Integer integer = flowingWaterService.registerUpFlowingWater(shopkeeperQo);
        if (integer == 0){
            throw new ServiceException(ResultCode.ERROR);
        }
        return rSet;
    }
}
